#include "TutorialApplication.h"
 
//-------------------------------------------------------------------------------------
ITutorial01::ITutorial01(void) {
}
//-------------------------------------------------------------------------------------
ITutorial01::~ITutorial01(void) {
}
 
//-------------------------------------------------------------------------------------
void ITutorial01::createScene(void) {
    mSceneMgr->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));

    mEntity = mSceneMgr->createEntity("Robot", "robot.mesh");
    mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotMesh", Ogre::Vector3(0.0f, 0.0f, 25.0f));
    mNode->attachObject(mEntity);

    mWalkList.push_back(Ogre::Vector3(550.0f,  0.0f,  50.0f ));
    mWalkList.push_back(Ogre::Vector3(-100.0f,  0.0f, -200.0f));

    Ogre::Entity *ent = mSceneMgr->createEntity("Knot1", "knot.mesh");
    Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Knot1Node",
                                                                                Ogre::Vector3(0.0f, -10.0f,  25.0f));
    node->attachObject(ent);
    node->setScale(0.1f, 0.1f, 0.1f);
     
    ent = mSceneMgr->createEntity("Knot2", "knot.mesh");
    node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Knot2Node",
                                                               Ogre::Vector3(550.0f, -10.0f,  50.0f));
    node->attachObject(ent);
    node->setScale(0.1f, 0.1f, 0.1f);
             
    ent = mSceneMgr->createEntity("Knot3", "knot.mesh");
    node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Knot3Node",
                                                               Ogre::Vector3(-100.0f, -10.0f,-200.0f));
    node->attachObject(ent);
    node->setScale(0.1f, 0.1f, 0.1f);

    mCamera->setPosition(90.0f, 280.0f, 535.0f);
    mCamera->pitch(Ogre::Degree(-30.0f));
    mCamera->yaw(Ogre::Degree(-15.0f));
}

void ITutorial01::createFrameListener(void) {
    BaseApplication::createFrameListener();
    mAnimationState = mEntity->getAnimationState("Idle");
    mAnimationState->setLoop(true);
    mAnimationState->setEnabled(true);

    mWalkSpeed = 35.0f;
    mDirection = Ogre::Vector3::ZERO;
}

bool ITutorial01::nextLocation(void) {
    if (mWalkList.empty())
        return false;

    mDestination = mWalkList.front();
    mWalkList.pop_front();

    mDirection = mDestination - mNode->getPosition();
    mDistance = mDirection.normalise();

    return true;
}
 
bool ITutorial01::frameRenderingQueued(const Ogre::FrameEvent &evt){
    if (mDirection == Ogre::Vector3::ZERO) {
        if (nextLocation()) {
            mAnimationState = mEntity->getAnimationState("Walk");
            mAnimationState->setLoop(true);
            mAnimationState->setEnabled(true);				
        }
    } else {
        Ogre::Real move = mWalkSpeed * evt.timeSinceLastFrame;
        mDistance -= move;
        if (mDistance <= 0.0f) {                 
            mNode->setPosition(mDestination);
            mDirection = Ogre::Vector3::ZERO;				
            if (!nextLocation()){
                mAnimationState = mEntity->getAnimationState("Die");
                mAnimationState->setLoop(true);
                mAnimationState->setEnabled(true);
            } else {
                Ogre::Vector3 src = mNode->getOrientation() * Ogre::Vector3::UNIT_X;

                if ((1.0f + src.dotProduct(mDirection)) < 0.0001f) {
                    mNode->yaw(Ogre::Degree(180));						
                } else {
                    Ogre::Quaternion quat = src.getRotationTo(mDirection);
                    mNode->rotate(quat);
                }
            }
        } else
            mNode->translate(mDirection * move);
    } 

    mAnimationState->addTime(evt.timeSinceLastFrame);
    return BaseApplication::frameRenderingQueued(evt);

}
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
    int main(int argc, char *argv[])
#endif
    {
        // Create application object
        ITutorial01 app;
 
        try {
            app.go();
        } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
            std::cerr << "An exception has occured: " <<
                e.getFullDescription().c_str() << std::endl;
#endif
        }
 
        return 0;
    }
 
#ifdef __cplusplus
}
#endif
